/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package projet_maths_svn;

import java.util.*;

/**
 *
 * @author JR
 */
public class Engine {
    static List<Solution> historique = new LinkedList<>();

    public static void GeneratesHistorique(int nbEntries)
    {
        System.out.println("Generation de l'historique:");
        Random rn = new Random();
        for (int i = 0 ; i < nbEntries ; i++)
        {
            int Rnd;
            List<Integer> tmpList = new LinkedList<>();
            do
            {
                Rnd = rn.nextInt(49)+1;
                if (!tmpList.contains(Rnd))
                {
                    tmpList.add(Rnd);
                }
            } while (tmpList.size() < 4);
            tmpList.add(rn.nextInt(9)+1);
            List<Token> tmpTokenList = new LinkedList<>();
            for (Integer in : tmpList)
            {
                tmpTokenList.add(new Token(in,0));
            }
            
            Solution s = new Solution(tmpTokenList,new Token(rn.nextInt(9)+1,0));
            historique.add(s);
            //System.out.println(s.ToString());
        }
        System.out.println("Fin de la génération de l'historique");
    }
    
    public static void Add(Solution s)
    {
        historique.add(s);
    }
    
    public static String ToString(List<Token> aList)
    {
        String tmp = "";
        for (Token t : aList)
        {
            tmp += t.ToStringChance();
        }
        return tmp;
    }
    
    public static String ToAllString(List<Token> aList)
    {
        String tmp ="";
        double tmpChance = 0;
        double tmpLucky = 0;
        double tmpChancePoisson = 0;
        double tmpLuckyPoisson = 0;
        for (Token t : aList)
        {
            tmp += t.ToStringAll() + "\n";
            tmpChance += t.chance;
            tmpLucky += t.chanceLucky;
            tmpChancePoisson += t.chancePoisson;
            tmpLuckyPoisson += t.chanceLuckyPoisson; 
            
        }
        tmp += "Total Chance: " + tmpChance + "\n";
        tmp += "Total Lucky : " + tmpLucky + "\n";
        tmp += "Total Chance Poisson: " + tmpChancePoisson + "\n";
        tmp += "Total Lucky Poisson : " + tmpLuckyPoisson + "\n";
        return tmp;
    }
    
    public static String ToStringChances(List<Token> aList)
    {
        String tmp = "";
        for (Token t : aList)
        {
            tmp += t.ToStringChance();
        }
        return tmp;
    }    
    
    public static double Combinatoire(int n , int p)
    {
        if (p > n)
        {
            return 0;
        }
        else
        {
            double numer = Facto(n);
            double denum = Facto(n-p)*Facto(p);
            double tmp = numer/denum;
            return tmp;
        }
    }
    
    public static double Facto(int i)
    {
        double tmp = i;
        while (i > 1)
        {
            i--;
            tmp = tmp * i;
        }
        return tmp;
    }
    
    public static int GetOccurences(int i)
    {
        int tmp = 0;
        for (Solution s : historique)
        {
            if (s.Has(i))
            {
                tmp++;
            }
        }
        return tmp;
    }
    
    public static int GetOccurencesOfLucky(int i)
    {
        int tmp = 0;
        for (Solution s : historique)
        {
            if (s.HasLucky(i))
            {
                tmp++;
            }
        }
        return tmp;
    }
    
    public static double ChancesOfAInNextGame(int a)
    {
        double bino;
        if (a < 1 || a > 49)
        {
            bino = 0;
        }
        else
        {
            int n = historique.size() +1;
            int k = GetOccurences(a) +1;
            double p = (double) 1 / 49;
            System.out.print("B:[" + String.format("%02d",a) + "](k=" + String.format("%02d",k) + ")(n=" + String.format("%03d",n) + ")(p=" + p +")");
            double tmp1 = Combinatoire(n, k);
            double tmp2 = Math.pow(p, k);
            double tmp3 = Math.pow((1-p),(n-k));
            System.out.print("=> " + tmp1 + "*" + tmp2 + "*" + tmp3 + "= ");
            bino = tmp1*tmp2*tmp3;
        }
        System.out.println(bino);
        return bino;
    }
    
    public static double ChancesOfALuckyInNextGame(int a)
    {
        double bino;
        if (a < 1 || a > 10)
        {
            return 0;
        }
        else
        {
            int n = historique.size() +1;
            int k = GetOccurencesOfLucky(a) +1;
            double p = (double) 1 / 10;
            double tmp1 = Combinatoire(n, k);
            double tmp2 = Math.pow(p, k);
            double tmp3 = Math.pow((1-p),(n-k));
            bino = tmp1*tmp2*tmp3;
        }
        return bino;
    }
        
    public static Carte BestCardOf(int nbNum)
    {
        List<Token> allTokens = new LinkedList<>();
                
        for (int i = 1 ; i < 50 ; i++)
        {
            allTokens.add(new Token(i));
            System.out.println("------------------------------------------------");
        }
        
        boolean sorted = false;
        while (!sorted)
        {
            sorted = true;
            for (int i = 0 ; i < allTokens.size()-1 ; i++)
            {
                if (allTokens.get(i).chance < allTokens.get(i+1).chance ) //On met le plus grand devant
                {
                    allTokens.add(i,allTokens.get(i+1));
                    allTokens.remove(i+2);   
                    sorted = false;
                }
            }
        }
        
        Carte bestOf = new Carte(allTokens.subList(0, nbNum));
        
        
        Token bestLucky = allTokens.get(0);
        for (Token t : allTokens)
        {
            if (t.chanceLucky > bestLucky.chanceLucky)
            {
                bestLucky = t;
            }
        }
        
        bestOf.lucky = bestLucky;        
        
        System.out.println(Engine.ToAllString(allTokens));
        
        return bestOf;
        
    }
    
    public static double ChancesOfAInNextGamePoisson(int a)
    {
        double poisson;
        //System.out.print("Chances of " + a + "....");
        if (a < 1 || a > 49)
        {
            poisson = 0;
        }
        else
        {
            int n = historique.size() +1;
            int k = GetOccurences(a) +1;
            double p = (double) 1 / 49;
            double lambda = n*p;
            System.out.print("P:[" + String.format("%02d",a) + "](k=" + String.format("%02d",k) + ")(n=" + String.format("%03d",n) + ")(lambda=" + lambda +")");
            double elambda = Math.pow(Math.E,lambda*-1);
            double lambdapower = Math.pow(lambda, k);
            double kfact = Facto(k);
            poisson = elambda*lambdapower/kfact;
            System.out.print("=> " + elambda + "*" + lambdapower + "/" + kfact + "= ");
        }
        System.out.println(poisson);
        return poisson;
    }
    
    public static double ChancesOfALuckyInNextGamePoisson(int a)
    {
        double poisson;
        if (a < 1 || a > 10)
        {
            poisson = 0;
        }
        else
        {
            int n = historique.size() +1;
            int k = GetOccurencesOfLucky(a) +1;
            double p = (double) 1 / 10;
            double lambda = n*p;
            //System.out.print("P:[" + String.format("%02d",a) + "](k=" + String.format("%02d",k) + ")(n=" + String.format("%03d",n) + ")(lambda=" + lambda +")");
            double elambda = Math.pow(Math.E,lambda*-1);
            double lambdapower = Math.pow(lambda, k);
            double kfact = Facto(k);
            poisson = elambda*lambdapower/kfact;
            //System.out.print("=> " + elambda + "*" + lambdapower + "/" + kfact + "= ");
        }
        return poisson;
    }
    
}